package com.softserveinc.ita.kaiji.model.game;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.softserveinc.ita.kaiji.model.UserImpl;
import com.softserveinc.ita.kaiji.model.player.Player;
import com.softserveinc.ita.kaiji.model.player.PlayerFactory;
import com.softserveinc.ita.kaiji.model.player.bot.Bot.Types;

/**
 * 
 * @author Bohdan Shaposhnik
 * @author Eugene Semenkov
 * @version 2.4
 * @since 17.03.2014
 */

@Entity
@Table(name="games")
public class GameInfoImpl implements GameInfo {

	private static Logger logger = Logger.getLogger(GameInfoImpl.class);
	
	@Transient
	@Autowired
	private PlayerFactory playerFactory;
	
	@Id
	@GeneratedValue
	@Column(name = "id")
	private Long id;

	@Column(name = "name")
 	private String gameName = null;	

	@Column(name = "number_of_cards")
	private Integer numberOfCards = 0;
	
	@Column(name = "bot_type")
	@Enumerated(EnumType.ORDINAL)
	private Types botType = null;

	@Column(name = "game_type")
	@Enumerated(EnumType.ORDINAL)
    private Game.Type gameType;

    @Column(name="started")
    private Date gameStartTime;
    
    @Column(name="finished")
    private Date gameFinishTime;
	
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "game_user",
    		joinColumns = { @JoinColumn(name = "id_game") },
    		inverseJoinColumns = { @JoinColumn(name = "id_user") })
	private Set<UserImpl> users = new HashSet<UserImpl>();

	@Transient
    private String ownerName;    
    
    @Transient
	private boolean isBotGame = false;
    
    @Transient
	private Set<Player> players = new HashSet<Player>();
	
	public GameInfoImpl(){}
	public GameInfoImpl(
			String gameName
			, String ownerName
			, Integer numberOfCards
			, boolean isBotGame
			, Types botType
			, Set<Player> players){
		this.gameName = gameName;
		this.ownerName = ownerName;
		this.numberOfCards = numberOfCards;
		this.isBotGame = isBotGame;
		this.players=players;
		this.botType = botType;
		if (this.isBotGame) {
			if (logger.isDebugEnabled()){
				logger.trace("GameInfoImpl: the mod is: bot VS player");}
		}
	}
	
	@Override
	public String getOwnerName(){
		return ownerName;
	}
	
	// adds only humanPlayers
	
	@Override
	public boolean isBotGame() {
		return isBotGame;
	}
	
	public void setBotGame(boolean isBotGame) {
		this.isBotGame = isBotGame;
	}

	@Override
	public String getGameName() {
		return gameName;
	}
	
	public void setGameName(String gameName) {
		this.gameName = gameName;
	}	

	@Override
	public Integer getNumberOfCards() {
		return numberOfCards;
	}
	
	public void setNumberOfCards(int numberOfCards) {
		this.numberOfCards = numberOfCards;
	}

	@Override
	public Types getBotType() {
		return botType;
	}

    @Override
    public void setGameType(Game.Type gameType) {
        this.gameType = gameType;
    }

    @Override
    public Game.Type getGameType() {
        return gameType;
    }

    @Override
    public Date getGameStartTime() {
        return gameStartTime;
    }

    @Override
    public void setGameStartTime(Date gameStartTime) {
        this.gameStartTime = gameStartTime;
    }

    @Override
    public Date getGameFinishTime() {
        return gameFinishTime;
    }

    @Override
    public void setGameFinishTime(Date gameFinishTime) {
        this.gameFinishTime = gameFinishTime;
    }

    public void setBotType(Types botType) {
		this.botType = botType;
	}

	public Long getId() {
		return id;
	}
	
	public void setId(Long id) {
		this.id = id;
	}
	
	@Override
	public Set<Player> getPlayers() {
		return players;
	}
	
	public Set<UserImpl> getUsers() {
		
		users.clear();
		
		for(Player player: players) {
			
			UserImpl user = new UserImpl();
			user.setId(player.getId());
			user.setName(player.getName());
			
			users.add(user);
			
		}
		
		return users;
	}
	
	public void setUsers(Set<UserImpl> users) {
		for(UserImpl user: users) {
			players.add(playerFactory.makePlayer(user, this.numberOfCards));			
		}
	}
	
	public void setPlayerFactory(PlayerFactory playerFactory) {
		this.playerFactory = playerFactory;
	}

}
